/**
 * to implement Java Ca&La we need just few interfaces
 */
package interfaces.kernel;

import java.io.File;




/**
 * @author Joubert
 * @version 1.0
 * 
 * - the developer API 
 * 
 */
public interface JCL_facade {
	
	
	/**
	 * 
	 * @param serviceClass the class to be executed remotely
	 * @param nickName the class name to be used by JCL
	 * @return true if it is registered, false otherwise
	 */
	public abstract boolean register (Class<?> serviceClass, String nickName);
	
	/**
	 * @param jars the jars files necessary to execute a class remotely. The first jar file is the user application. The remaining are dependencies
	 * @param classToBeExecuted the class name to be used by JCL. just the simple name. no packages. no .class extension
	 * @return true if it is registered, false otherwise
	 */
	public abstract boolean register (File[] jars, String classToBeExecuted);
	
	
	/**
	 * @param nickName the class, jar or exe component to be removed by JCL
	 * @return true if it is removed, false otherwise
	 */
	public abstract boolean unRegister (String nickName);
	
		
	/**
	 * the method "EXECUTE" is called by default
	 * 
	 * @param objectNickname - the object nickname defined by the developer
	 * @param args - the method parameters values
	 * @return the task id, used to get the result asynchronously. The task id is used with getResulBlocking(tID) or getResultUnblocking(tID) 
	 */
	public abstract String execute (String objectNickname, Object... args);
	
	
	
	/**
	 * explicit method name is the unique difference
	 * 
	 * @param className - the full class name, i.e., .class file name
	 * @param methodName - the object method name to be executed
	 * @param args - the method parameters values
	 * @return the task id, used to get the result asynchronously. The task id is used with getResulBlocking(tID) or getResultUnblocking(tID)  
	 */
	public abstract String execute (String className, String methodName, Object...args);
	
		
	/**
	 * 
	 * get a method result or a wait condition. If a wait condition is obtained, the caller is blocked  
	 * until the result arrives or a timeout is achieved
	 * @param ID - the method or task identification
	 * 
	 * @return the result OR an error
	 */
	public abstract JCL_result getResultBlocking(String ID);
	
	/**
	 * get a method result or null. The caller is never blocked. Asynchronous get of results.
	 * 
	 * @param ID - the method or task identification
	 * 
	 * @return the result or error or null, the last indicating processing
	 */
	public abstract JCL_result getResultUnblocking(String ID);
	
	/**
	 * @param ID - the task name or the task id in asynchronous executions
	 * @return - return the removed result. null if no such result exists.
	 * 
	 */
	public abstract JCL_result removeResult(String ID);
	
	/**
	 * creates a global variable with name equals nickName, user typed according to jar files 
	 * and a class name varName. The args array sets user variable initial values. 
	 * The class name varName must be equal the .class file in the jar file.
	 * @param nickname - the user nickname
	 * @param varName - the variable name. varName must be equal the .class file in the jar file.
	 * @param defaultVarValue - the default variable value
	 * @return - return the instance if the variable is created. null otherwise.
	 */
	public abstract Object instantiateGlobalVar(String nickname, String varName, File[] jars, Object[] defaultVarValue);

	/**
	 * creates a global variable with name equals varName. JCL uses the user object 
	 * instance instead of creating an instance internally. It does not works with user types. 
	 * Only Java types.
	 * @param varName - the variable name
	 * @param instance - a user variable value
	 * @return - return true if the variable is registered. False otherwise.
	 */
	public abstract boolean instantiateGlobalVar(String varName, Object instance);

	/**
	 * removes a user global variable with name varName from JCL
	 * 
	 * @param varName - the variable name
	 * @return - return true if the variable is set null. False otherwise.
	 * if the variable is previously locked the destroy will return false.
	 * the user must unlock first and destroy after.
	 */
	public abstract boolean destroyGlobalVar(String varName);

	
	/**
	 * Updates the variable value. The setValue is not performed if a variable is previously locked.  
	 * 
	 * @param varName - global variable name
	 * @param value - global variable value
	 * @return true if value is correctly updated or false otherwise
	 */
	public abstract boolean setValue (String varName, Object value);
	
	/**
	 * Updates the variable value. Unlock a variable if it is previously locked.  
	 * 
	 * @param varName - global variable name
	 * @param value - global variable value
	 * @return true if value is correctly updated or false otherwise
	 */
	public abstract boolean setValueUnlocking (String varName, Object value);
	
	
	/**
	 * gets a variable varName value 
	 * 
	 * @param varName - global variable name
	 * @return the global variable value or an error or null if no variable exists
	 */
	public abstract JCL_result getValue(String varName);
	
	
	/**
	 * gets a variable varName value and locks varName access. 
	 * This is a simple implementation of critical sections. 
	 * The variable is locked and writed by a single process until a setValueUnlocking(varName) call. 
	 * Other processes can only read such a variable, using JCL getValue(varName) method
	 * @param varName - global variable name
	 * @return the global variable value or an error or null if no variable exists. 
	 * If there is a correct value, the JCL_Result also stores a lock ticket,
	 * used to set a value or simple unlock the variable.
	 * the pair getValueLocking and setValueUnlocking implements critical sections in Java Ca&La
	 */
	public abstract JCL_result getValueLocking(String varName);
	
	
	/**
	 * set null all objects
	 */
	public abstract void destroy();
	
	/**
	 * verify if there is a task registered in JCL
	 * 
	 * @param nickName the task name
	 * @return true if JCL contains such a task, false otherwise
	 */
	public abstract boolean containsTask(String nickName);
	
	/**
	 * verify if there is a global variable registered in JCL
	 * 
	 * @param nickName the global var name
	 * @return true if JCL contains such a global variable, false otherwise
	 */
	public abstract boolean containsGlobalVar(String nickName);

}
